﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AdmLaboratorios.DAO;
using AdmLaboratorios.DTO;
using System.Data.SqlClient;
using System.Data;

namespace AdmLaboratorios.Business
{
    public static class Stock
    {
        static StockDAO daoStock = DAOFactory.Get<StockDAO>();
        static ValeConsumoDevolucionItemDAO daoItem = DAOFactory.Get<ValeConsumoDevolucionItemDAO>();
        static ValeConsumoDevolucionDAO daoVale = DAOFactory.Get<ValeConsumoDevolucionDAO>();

        public static DataTable GetAprobados(PartnerDTO partner, bool filtraPorPartener)
        {
            if (partner != null && filtraPorPartener)
                return daoStock.Consulta("Estado='APROBADO' AND IdPartner = " + partner.Id);
            else
                return daoStock.Consulta("Estado='APROBADO'");
        }

        public static DataTable GetCuarentena(PartnerDTO partner, bool filtraPorPartener)
        {
            if (partner != null && filtraPorPartener)
                return daoStock.Consulta("Estado='CUARENTENA' AND IdPartner = " + partner.Id);
            else
                return daoStock.Consulta("Estado='CUARENTENA'");
        }

        public static StockDTO Get(int id)
        {
            return daoStock.Read(id);
        }

        internal static void ChangeState(InformeLaboratorioDTO cc, SqlTransaction tran)
        {
            try
            {
                StockDTO stock = daoStock.Read(cc.IdStock);

                //Coloco el nuevo estado y valores.
                stock.Estado = cc.Resultado;
                stock.FactorCorreccion = cc.CoeficienteCorreccion;
                stock.NroAnalisis = cc.NroAnalisis;
                //--

                daoStock.Update(stock, stock.Id, tran);
                daoStock.Log(LogDTO.eAcciones.Modificacion, "Cambio de Estado de Stock.",
                    stock.Id, tran, "Stock");
                
            }
            catch (Exception ex)
            {
                throw new Exception("ChangeState", ex);
            }
        }

        private static void RemoveFromStock(Vale vale, SqlTransaction tran)
        {
            try
            {
                StockDTO stock;
                foreach (ValeConsumoDevolucionItemDTO item in vale.Items)
                {
                    stock = daoStock.Read(item.IdStock);

                    //Incremento la cantidad del registro en el stock.
                    stock.Cantidad -= item.Cantidad;
                    //--

                    daoStock.Update(stock, stock.Id, tran);
                    daoStock.Log(LogDTO.eAcciones.Alta, "Resta de Cantidad en Stock.",
                        stock.Id, "Cantidad", (stock.Cantidad + item.Cantidad).ToString(), stock.Cantidad.ToString(), tran, "Stock");
                }
            }
            catch (Exception ex)
            {
                throw new Exception("RemoveFromStock", ex);
            }
        }

        private static void AddToStock(Vale vale, SqlTransaction tran)
        {
            try
            {
                StockDTO stock;
                foreach (ValeConsumoDevolucionItemDTO item in vale.Items)
                {
                    stock = new StockDTO();

                    //Creo el registro de stock.
                    stock.Activo = true;
                    stock.Cantidad = item.Cantidad;
                    stock.FactorCorreccion = 1;
                    stock.IdPartner = vale.Partner.Id; 
                    stock.IdProducto = item.IdProducto;
                    stock.IdStock = null;
                    stock.NroAnalisis = item.NroAnalisis;


                    if (stock.NroAnalisis.Trim() == string.Empty)
                        stock.Estado = eStockEstado.CUARENTENA.ToString();
                    else
                        stock.Estado = eStockEstado.APROBADO.ToString();
                    //--

                    stock = daoStock.Create(stock, tran);
                    daoStock.Log(LogDTO.eAcciones.Alta, "Alta de Producto en Stock. VALE DEVOLUCION nro: " + vale.ValeConsumoDevolucion.Id, stock.Id, tran, "Stock");

                    item.IdStock = stock.Id;
                    //Stock.val InformesRecepcion.SetStock(item, stock, tran);
                }


                //StockDTO stock;
                //foreach (ValeConsumoDevolucionItemDTO item in vale.Items)
                //{
                //    stock = daoStock.Read(item.IdStock);

                //    //Incremento la cantidad del registro en el stock.
                //    stock.Cantidad += item.Cantidad;
                //    //--

                //    daoStock.Update(stock, stock.Id, tran);
                //    daoStock.Log(LogDTO.eAcciones.Alta, "Suma de Cantidad en Stock.", 
                //        stock.Id, "Cantidad", (stock.Cantidad - item.Cantidad).ToString(), stock.Cantidad.ToString(), tran, "Stock");
                //}
            }
            catch (Exception ex)
            {
                throw new Exception("AddToStock", ex);
            }
        }

        internal static void AddToStock(InformeRecepcionDTO Ir, List<InformeRecepcionItemDTO> items, SqlTransaction tran)
        {
            try
            {
                StockDTO stock;
                foreach (InformeRecepcionItemDTO item in items)
                {
                    stock = new StockDTO();

                    //Creo el registro de stock.
                    stock.Activo = true;
                    stock.Cantidad = item.Cantidad;
                    stock.FactorCorreccion = 1;
                    stock.IdPartner = Ir.IdPartner;
                    stock.IdProducto = item.IdProducto;
                    stock.IdStock = null;
                    stock.NroAnalisis = item.NroAnalisis;

                    if (stock.NroAnalisis.Trim() == string.Empty)
                        stock.Estado = eStockEstado.CUARENTENA.ToString();
                    else
                        stock.Estado = eStockEstado.APROBADO.ToString();
                    //--

                    stock = daoStock.Create(stock, tran);
                    daoStock.Log(LogDTO.eAcciones.Alta, "Alta de Producto en Stock. IR nro: " + Ir.Id, stock.Id, tran, "Stock");

                    InformesRecepcion.SetStock(item, stock, tran);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("AddToStock", ex);
            }
        }



        public static DataTable ValeConsumoItems(OrdenProduccionDTO op)
        {
            return daoStock.ValeConsumoItems(op);
        }

        //public static DataTable ValeDevolucionItems(OrdenProduccionDTO op)
        //{
        //    return daoStock.ValeDevolucionItems(op);
        //}

        public static Vale SaveConsumo(Vale vale)
        {
            ValeConsumoDevolucionItemDTO itemAux;
            List<ValeConsumoDevolucionItemDTO> aux = new List<ValeConsumoDevolucionItemDTO>();

            try
            {
                using (SqlTransaction tran = daoVale.IniciarTransaccion())
                {
                    var cabecera = daoVale.Create(vale.ValeConsumoDevolucion, tran);

                    foreach (ValeConsumoDevolucionItemDTO item in vale.Items)
                    {
                        itemAux = new ValeConsumoDevolucionItemDTO();

                        item.Activo = true;
                        item.IdValeConsumoDevolucion = cabecera.Id;
                        itemAux = daoItem.Create(item, tran);

                        daoItem.Log(LogDTO.eAcciones.Alta, "Alta de Item del VALE CONSUMO nro: " + cabecera.Id, itemAux.Id, tran);
                        aux.Add(itemAux);
                    }

                    daoVale.Log(LogDTO.eAcciones.Alta, "Alta de VALE CONSUMO", cabecera.Id, tran);

                    if (vale.ValeConsumoDevolucion.Tipo.ToUpper() == eValeTipo.CONSUMO.ToString())
                    {
                        RemoveFromStock(vale, tran);
                    }
                    else
                    {
                        AddToStock(vale, tran);
                    }

                    daoVale.CommitTransaccion(tran);

                    vale.Items = aux;
                    return vale;
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Save", ex);
            }
        }

        public static DataTable Consulta(string estado, string filtro)
        {
            if (estado != eStockEstado.TODO.ToString())
                return daoStock.Consulta(string.Format("A.Estado = '{0}' AND (B.Nombre LIKE '%{1}%' OR C.Nombre LIKE '%{1}%' OR C.NombreComercial LIKE '%{1}%')", 
                    estado.Trim().ToUpper(),
                    filtro));
            else
                return daoStock.Consulta(string.Format("(B.Nombre LIKE '%{0}%' OR C.Nombre LIKE '%{0}%' OR C.NombreComercial LIKE '%{0}%')",
                    filtro));
        }

        public static DataTable ConsultaValtes(string tipo)
        {
            return daoVale.Consulta(string.Format("Tipo = '{0}'", tipo));
        }

        public static DataTable ConsultaValtes(string tipo, OrdenProduccionDTO op)
        {
            return daoVale.Consulta(string.Format("Tipo = '{0}' AND IdOrdenProduccion = {1}", tipo, op.Id));
        }

        public static ValeConsumoDevolucionDTO GetVale(int id)
        {
            return daoVale.Read(id);
        }

        public static DataTable GetValeItemsTable(int id)
        {
            return daoItem.GetValeItemsTable(id);
        }

        public static Vale SaveDevolucion(Vale vale)
        {
            ValeConsumoDevolucionItemDTO itemAux;
            List<ValeConsumoDevolucionItemDTO> aux = new List<ValeConsumoDevolucionItemDTO>();

            try
            {
                using (SqlTransaction tran = daoVale.IniciarTransaccion())
                {
                    var cabecera = daoVale.Create(vale.ValeConsumoDevolucion, tran);
                    daoVale.Log(LogDTO.eAcciones.Alta, "Alta de VALE DEVOLUCION", cabecera.Id, tran);

                    //Creo los items en el Stock (y lleno el IdStock).
                    AddToStock(vale, tran);

                    //Creo los items del vale (relacionados al stock.
                    foreach (ValeConsumoDevolucionItemDTO item in vale.Items)
                    {
                        itemAux = new ValeConsumoDevolucionItemDTO();

                        item.Activo = true;
                        item.IdValeConsumoDevolucion = cabecera.Id;
                        itemAux = daoItem.Create(item, tran);

                        daoItem.Log(LogDTO.eAcciones.Alta, "Alta de Item del VALE DEVOLUCION nro: " + cabecera.Id, itemAux.Id, tran);
                        aux.Add(itemAux);
                    }

                    daoVale.CommitTransaccion(tran);

                    vale.Items = aux;
                    return vale;
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Save", ex);
            }
        }
        
        public static void EjecutarVencimientos()
        {
            try
            {
                //Vencimientos del día.
                DataTable dtVencimientos = daoStock.GetVencimientos();

                if (dtVencimientos.Rows.Count > 0)
                {
                    using (SqlTransaction tran = daoStock.IniciarTransaccion())
                    {
                        StockDTO s;

                        //Pongo en cuarentena los registros de Stock vencidos.
                        foreach (DataRow dr in dtVencimientos.Rows)
                        {
                            s = daoStock.Read((int)dr["Id"]);
                            s.Estado = eStockEstado.CUARENTENA.ToString().ToUpper();
                            daoStock.Update(s, s.Id, tran);
                            daoStock.Log(LogDTO.eAcciones.Modificacion, "Vencimiento de Stock.", s.Id, tran);
                        }

                        daoStock.CommitTransaccion(tran);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Stock.EjecutarVencimientos", ex);
            }

        }

        public static void Ajuste(StockDTO stock, string observaciones)
        {
            try
            {
                using (SqlTransaction tran = daoStock.IniciarTransaccion())
                {
                    string logOld = string.Empty;
                    string logNew = string.Empty;
                    
                    StockDTO old = daoStock.Read(stock.Id);

                    logOld = string.Format("NroAnalisis: {0} | Cantidad: {1} | FactorCorreccion: {2} Estado: {3}", 
                        old.NroAnalisis, old.Cantidad, old.FactorCorreccion, old.Estado);

                    logNew = string.Format("NroAnalisis: {0} | Cantidad: {1} | FactorCorreccion: {2} Estado: {3}",
                        stock.NroAnalisis, stock.Cantidad, stock.FactorCorreccion, stock.Estado);

                    daoStock.Update(stock, stock.Id, tran);
                    daoStock.Log(LogDTO.eAcciones.Modificacion, "Ajuste de Stock | Observaciones: " + observaciones, stock.Id, string.Empty, logOld, logNew, tran);
                    daoStock.CommitTransaccion(tran);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Stock.Ajuste", ex);
            }
        }
    }
}
